#ifndef PROCESS_POOL

#define PROCESS_POOL
#include"task.hpp"
#include<string>
#include<unistd.h>
#include <sys/types.h>
#include <sys/wait.h>


class Channel
{
public:
	Channel(int wfd,int rfd,pid_t subpid,int num)
	:_wfd(wfd)
	,_rfd(rfd)
	,_subpid(subpid)
	,_num(num)
	{
		_name = "Channel-" + std::to_string(subpid) + "-" + std::to_string(_num);
	}

	int Getwfd()
	{
		return  _wfd;
	}

	std::string Getname()
	{
		return _name;
	}

	pid_t Getpid()
	{
		return _subpid;
	}

	~Channel()
	{

	}


private:
	int _wfd;
	int _rfd;
	std::string _name;
	pid_t _subpid;
	int _num;
};

class PPool
{
public:
	PPool()
	:_next(0)
	{
		
	}

	void Write(int wfd,int code)
	{
		write(wfd,&code,sizeof(code));
	}

	void Read(int rfd)
	{
		while(true)
		{
			int code = 0;
		 	int n = read(rfd,&code,sizeof(code));
			if(-1 == n)
			{
				std::cerr << "read fail " << std::endl;
				return;
			}
			else if(0 == n)
			{
				std::cout << "子进程退出" << std::endl; 
				break;
			}
			else
			{
				if( n != sizeof(code))
				{
					std::cerr << "read byte number error" << std::endl;
					return;
				}
				else
				{
					std::cout<< "子进程" << getpid() << "收到任务码" <<code<<std::endl;
					_t.Execute(code);
				}
			}
		}
	}

	void Start()
	{
		for(int i = 0;i < 5;++i)
		{
			int pipefd[2] = {0};
			int ret = pipe(pipefd);
			if(ret == -1)
			{
				std::cerr << "创建进程池失败" <<std::endl;
				return;
			}
			pid_t subpid = fork();
			if(-1 == subpid)
			{
				std::cerr << "fork失败" <<std::endl;
				return;
			}
			else if(0 == subpid)
			{
				//子
				CloseAllW();
				close(pipefd[1]);
				Read(pipefd[0]);
				close(pipefd[0]);
				exit(0);
			}
			else
			{
				//父
				close(pipefd[0]);
				_pp.emplace_back(pipefd[1],pipefd[0],subpid,i);
			}
		}
	}

	~PPool()
	{

	}

	

	Channel& Select()
	{
		int temp = _next++;
		_next %= _pp.size();
		return _pp[temp];
	}

	void Run()
	{	
		int cnt = 10;
		while(cnt--)
		{
		int code = _t.MakeCode();
		Channel c = Select();
		std::cout << "给" << c.Getname() << "发送了" << code << std::endl; 
		Write(c.Getwfd(),code);
		sleep(1);
		}
	}

	void CloseAllW()
	{
		for(auto&  e: _pp)
		{
			close(e.Getwfd());
		}
	}

	void Stop()
	{
		for(auto& e : _pp)
		{
			close(e.Getwfd());
			waitpid(e.Getpid(),nullptr,0);
		}
	}
	

private:
	std::vector<Channel> _pp;
	int _next;
	Task _t;
};

#endif

